package com.jiunuan.live.core.server.handler.impl;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.jiunuan.live.common.interfaces.topic.ImCoreServerProviderTopicNames;
import com.jiunuan.live.core.server.common.ChannelHandlerContextCache;
import com.jiunuan.live.core.server.common.ImContextUtils;
import com.jiunuan.live.core.server.common.ImMsg;
import com.jiunuan.live.core.server.handler.SimplyHandler;
import com.jiunuan.live.framework.redis.starter.key.IMCoreServerProviderCacheKeyBuilder;
import com.jiunuan.live.im.constants.ImMsgCodeEnum;
import com.jiunuan.live.im.core.server.interfaces.dto.ImOfflineDTO;
import com.jiunuan.live.im.dto.ImMsgBody;
import io.netty.channel.ChannelHandlerContext;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.MQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @Author: JiuNuan
 * @CreateTime: 2024-08-10 21:49
 * @Description: 登出消息包实现类, 登出消息处理同一收拢到这一个类中
 */
@Slf4j
@Component
public class LogoutMsgHandler implements SimplyHandler {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private IMCoreServerProviderCacheKeyBuilder cacheKeyBuilder;
    @Resource
    private MQProducer mqProducer;
    /**
     * 消息处理函数，根据code匹配不同实现类
     *
     * @param ctx
     * @param imMsg
     */
    @Override
    public void handler(ChannelHandlerContext ctx, ImMsg imMsg) {
        Long userId = ImContextUtils.getUserId(ctx);
        Integer appId = ImContextUtils.getAppId(ctx);
        if(userId == null || appId == null){
            ctx.close();
            log.error("[LogoutMsgHandler]attr error,imMsg：" + imMsg);
            throw new RuntimeException("attr error");
        }
        // 将im消息回写给客户端
        logoutMsgNotice(ctx,userId,appId);
        logoutSuccessHandler(ctx, userId, appId);

    }

    /**
     * 登出的时候，发送确认信号，这个是正常网络断开才会发送，异常断线则不发送
     *
     * @param ctx
     * @param userId
     * @param appId
     */
    private void logoutMsgNotice(ChannelHandlerContext ctx, Long userId, Integer appId) {
        // 将im消息回写给客户端
        ImMsgBody respBody = new ImMsgBody();
        respBody.setAppId(appId);
        respBody.setUserId(userId);
        respBody.setData("true");
        ImMsg respMsg = ImMsg.build(ImMsgCodeEnum.IM_LOGOUT_MSG.getCode(), JSON.toJSONString(respBody));
        ctx.writeAndFlush(respMsg);
        ctx.close();
    }

    /**
     * 如果用户成功登录，就处理相关记录
     */
    public void logoutSuccessHandler(ChannelHandlerContext ctx, Long userId, Integer appId) {
        log.info("[LogoutMsgHandler]logout success,userId:{},appid:{}", userId, appId);
        // 理想情况下，客户端断线的时候，会发送一个断线消息包
        ChannelHandlerContextCache.remove(userId);
        // 删除redis中的绑定信息
        stringRedisTemplate.delete(cacheKeyBuilder.buildIMBindIpKey(appId, userId));
        // 删除上下文信息
        ImContextUtils.removeUserId(ctx);
        ImContextUtils.removeAppId(ctx);
        sendLogoutMQ(ctx, userId, appId);
    }

    /**
     * 登出的时候发送mq消息
     *
     * @param ctx
     * @param userId
     * @param appId
     */
    public void sendLogoutMQ(ChannelHandlerContext ctx, Long userId, Integer appId) {
        ImOfflineDTO imOfflineDTO = new ImOfflineDTO();
        imOfflineDTO.setUserId(userId);
        imOfflineDTO.setAppId(appId);
        imOfflineDTO.setLoginTime(System.currentTimeMillis());

        Message message = new Message();
        message.setTopic(ImCoreServerProviderTopicNames.IM_OFFLINE_TOPIC);
        message.setBody(JSON.toJSONString(imOfflineDTO).getBytes());
        try {
            SendResult sendResult = mqProducer.send(message);
            log.info("[LogoutMsgHandler] result is {}", sendResult);
        } catch (Exception e) {
            log.error("[LogoutMsgHandler] error is: ", e);
        }
    }
}
